//
//  TGMItem.m
//  TravelGuideMdd
//
//  Created by BigPolarBear on 13-5-14.
//  Copyright (c) 2013年 mafengwo.com. All rights reserved.
//

#import "BaseItem.h"
#import "Utils_Swizzing.h"
#import <objc/runtime.h>

static NSMutableDictionary *PROPERTY_KEY_DICT = nil;

@interface BaseItem()
@property(nonatomic, strong)MFWJson *json;
@end

static NSMutableDictionary *allProptyReturnTypes = nil;

Class retClassForClassAndSelName(Class classs,NSString * selName)
{
    Class retClass = allProptyReturnTypes[NSStringFromClass(classs)][selName];
    if (retClass)
    {
        return retClass;
    }
    
    Class superClass = class_getSuperclass(classs);
    
    if (superClass)
    {
        return retClassForClassAndSelName(superClass, selName);
    }
    else
    {
        return nil;
    }
}

static NSString *proptyString(BaseItem *self, SEL _cmd)
{
    NSString *selName = NSStringFromSelector(_cmd);
    return [self stringForKey:selName];
}

static id proptyItem(BaseItem *self,SEL _cmd)
{
    NSString *selectorName = NSStringFromSelector(_cmd);
    NSString *keyName = selectorName; // key名字

    BaseItem *item = nil;
    NSString *itemKey = nil;
    
    @synchronized([BaseItem class]) {
        if (PROPERTY_KEY_DICT == nil) {
            PROPERTY_KEY_DICT = [@{} mutableCopy];
        }
        
        itemKey = PROPERTY_KEY_DICT[keyName];
        
        if (itemKey == nil) {
            itemKey = [NSString stringWithFormat:@"%@_item_getter_selector", selectorName];
        }
        
        item = objc_getAssociatedObject(self, (__bridge void *)itemKey);
    }
    
    if (item) {
        return item;
    }
    
    Class retClass = retClassForClassAndSelName(self.class, selectorName);
    MFWJson *json = [self.json jsonForKey:selectorName];
    if (json && retClass)
    {
        item = [[retClass alloc] initWithJson:json];
    }
    // 如果不能转化为指定类型  则不返回其他类型的值 即使该key有值
    else
    {
        
    }
    
    // 记录初次解析的array的值
    if (item) {
        @synchronized([BaseItem class]) {
            PROPERTY_KEY_DICT[selectorName] = itemKey;
            objc_setAssociatedObject(self, (__bridge void *)itemKey, item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
    }
    
    return item;
}

static char proptyChar(BaseItem *self,SEL _cmd)
{
    NSString *selName = NSStringFromSelector(_cmd);
    id obj = [self.json originValueForKey:selName];
    if (!obj)
    {
        return 0;
    }
    if ([obj isKindOfClass:[NSString class]])
    {
        NSString *str = obj;
        return (char)(str.intValue);
    }
    else if ([obj isKindOfClass:[NSNumber class]])
    {
        NSNumber *number = obj;
        return number.charValue;
    }
    else
    {
        return 0;
    }
}

static id proptyMFWJson(BaseItem *self, SEL _cmd)
{
    id value = [self.json originValueForKey:NSStringFromSelector(_cmd)];
    return [MFWJson jsonWithObject:value];
}

static int proptyInt(BaseItem *self,SEL _cmd)
{
    NSString *selName = NSStringFromSelector(_cmd);
    return  [self.json intValueForKey:selName];
}

static float proptyFloat(BaseItem *self,SEL _cmd)
{
    NSString *selName = NSStringFromSelector(_cmd);
    return  [self.json floatValueForKey:selName];
}

static double proptyDouble(BaseItem *self,SEL _cmd)
{
    NSString *selName = NSStringFromSelector(_cmd);
    return  [self.json doubleValueForKey:selName];
}

static id proptyOther(BaseItem *self,SEL _cmd)
{
    return [self.json originValueForKey:NSStringFromSelector(_cmd)];
}

static id proptyNSArray(BaseItem *self,SEL _cmd)
{
    NSString *selectorName = NSStringFromSelector(_cmd);
    NSString *keyName = selectorName; // key名字
    
    NSArray *retArr = nil;
    NSString *retArrKey = nil;
 
    @synchronized([BaseItem class]) {
        if (PROPERTY_KEY_DICT == nil) {
            PROPERTY_KEY_DICT = [@{} mutableCopy];
        }
        
        retArrKey = PROPERTY_KEY_DICT[keyName];
        
        if (retArrKey == nil) {
            retArrKey = [NSString stringWithFormat:@"%@_nsarray_getter_selector", selectorName];
        }
        
        retArr = objc_getAssociatedObject(self, (__bridge void *)retArrKey);
    }
    
    if (retArr) {
        return retArr;
    }
    
    Class elementClass = Nil;
    
    // 带解析字符串
    NSRange range = [keyName rangeOfString:@"_" options:NSBackwardsSearch];
    
    // 找到下杠则匹配为类型
    if (range.length > 0)
    {
        // 切分字符串
        NSString *checkType = [keyName substringFromIndex:(range.location+range.length)];
        Class typeClass = NSClassFromString(checkType);
        
        // 如果转化为类成功  并且是baseitem子类
        if (typeClass && [typeClass isSubclassOfClass:[BaseItem class]])
        {
            elementClass = typeClass;
            keyName = [keyName substringToIndex:range.location];
        }
    }

    retArr = [self.json originValueForKey:keyName];
    // 如果取到的空 或者不是数组
    if ([retArr isKindOfClass:[NSNull class]]
        || !retArr)
    {
        retArr = nil;
    }
    // 如果不是数组
    else if (![retArr isKindOfClass:[NSArray class]])
    {
        retArr = nil;
    }
    // 如果有类型
    else if (elementClass)
    {
        if (retArr.count)
        {
            retArr =  [elementClass arrayWithArrayDictionary:retArr];
        }
        else
        {
            retArr = nil;
        }
    }
    // 其他
    else
    {
        // do nothing
    }
    
    // 记录初次解析的array的值
    if (retArr) {
        @synchronized([BaseItem class]) {
            PROPERTY_KEY_DICT[selectorName] = retArrKey;
            objc_setAssociatedObject(self, (__bridge void *)retArrKey, retArr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        }
    }
    
    return retArr;
}

@implementation BaseItem

+ (Class)classFromeRetType:(const char*)returnType
{
    NSUInteger len = strlen(returnType);
    if (len > 3
        && returnType[0] =='@'
        && returnType[1] == '"'
        && returnType[len-1] == '"' )
    {
        NSUInteger newLen = len - 3;
        char name[newLen+1];
        memcpy(name, returnType + 2, newLen);
        name[newLen] = '\0';
        NSString *classname = [NSString stringWithUTF8String:name];
        return NSClassFromString(classname);
    }
    return Nil;
}

+ (void)resetSel:(const char*)aSelName retType:(const char*)aRetType
{
    Class class = [self classFromeRetType:aRetType];
    NSString *selName = [NSString stringWithUTF8String:aSelName];
    SEL sel = NSSelectorFromString(selName);
    if ([class isSubclassOfClass:[BaseItem class]])
    {
        if (!allProptyReturnTypes)
        {
            allProptyReturnTypes = [[NSMutableDictionary alloc] init];
        }
        NSString *key = NSStringFromClass(self);
        NSMutableDictionary *proptyDict = [allProptyReturnTypes valueForKey:key];
        if (!proptyDict)
        {
            proptyDict = [[NSMutableDictionary alloc] init];
            [allProptyReturnTypes setValue:proptyDict
                                    forKey:key];
        }
        
        [proptyDict setValue:class
                      forKey:selName];
        objc_changeMethod(self, sel, proptyItem);
    }
    else if (class == [NSString class] || [class isSubclassOfClass:[NSString class]])
    {
        objc_changeMethod(self, sel, proptyString);
    }
    else if (class == [NSArray class] || [class isSubclassOfClass:[NSArray class]])
    {
        objc_changeMethod(self, sel, proptyNSArray);
    }
    else if (class == [MFWJson class] || [class isSubclassOfClass:[MFWJson class]])
    {
        objc_changeMethod(self, sel, proptyMFWJson);
    }
    else
    {
        if (aRetType[0] == _C_CHR)
        {
            objc_changeMethod(self, sel, proptyChar);
        }
        else if (aRetType[0] == _C_INT)
        {
            objc_changeMethod(self, sel, proptyInt);
        }
        else if (aRetType[0] == _C_FLT)
        {
            objc_changeMethod(self, sel, proptyFloat);
        }
        else if (aRetType[0] == _C_DBL)
        {
            objc_changeMethod(self, sel, proptyDouble);
        }
        else
        {
            objc_changeMethod(self, sel, proptyOther);
        }
    }
}

+ (void)initialize
{
    if (self == [BaseItem class])
    {
        return;
    }
    
    unsigned int count = 0;
    objc_property_t *propertys = class_copyPropertyList(self, &count);
    for (NSUInteger i = 0 ; i < count ;i ++)
    {
        // 取得所有附加
        unsigned int pCount = 0;
        objc_property_attribute_t *list = property_copyAttributeList(propertys[i], &pCount);
        
        // getter名
        const char *getterName = NULL;
        const char *returnType = NULL;
        BOOL readonly = NO;
        BOOL isRewrite = YES;
        for (NSUInteger j = 0 ;j < pCount ; j++)
        {
            const char *name = list[j].name;
            const char *value = list[j].value;
            // getter
            if (strcmp(name, "G") == 0)
            {
                getterName = value;
            }
            
            // 返回值
            else if (strcmp(name, "T") == 0)
            {
                returnType = value;
            }
            
            // readonly
            else if (strcmp(name, "R") == 0)
            {
                readonly = YES;
            }
            
            // 有变量
            else if (strcmp(name, "V") == 0)
            {
                isRewrite = NO;
            }
        }
        if (NULL == getterName)
        {
            getterName = property_getName(propertys[i]);
        }

        // 只修改只读  并且没有重写函数的属性
        if (readonly && isRewrite == NO)
        {
            // 如果没有设置getter则默认为属性名
            [self resetSel:getterName retType:returnType];
        }
        free(list);
    }
    free(propertys);
}


/** 通过字典初始化 */
-(id)initWithDictionary:(NSDictionary*)dict
{
    self = [super init];
    if (self) {
        if ([dict isKindOfClass:[NSDictionary class]])
        {
            NSMutableDictionary* mutableDict = [NSMutableDictionary dictionaryWithDictionary:dict];
            _json = [MFWJson jsonWithObject:mutableDict];
        }
        else
        {
#ifdef DEBUG
            NSAssert(NO, @"BaseItem initWithDictionary param is not Dictionary type");
#endif
        }
    }
    
    return self;
}

- (id)initWithJson:(MFWJson*)json;
{
    self = [super init];
    if (self) {
        _json = json;
    }
    return self;
}

- (NSDictionary *)originDict
{
    return _json.jsonObj;
}
/** 从字典数组转化 */
+(NSArray*)arrayWithArrayDictionary:(NSArray*)arrayDict
{
    NSMutableArray* arrayItem = [NSMutableArray arrayWithCapacity:arrayDict.count];
    [arrayDict enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        id item = [[[self class] alloc] initWithDictionary:obj];
        [arrayItem addObject:item];
    }];
    
    return arrayItem;
}


/** 如果原始数据没有此key，则返回空字符串@"" */
-(NSString*)stringForKey:(NSString*)key
{
    return [self.json stringValueForKey:key defaultValue:@""];
}

-(MFWJson*)jsonForKey:(NSString*)key
{
    return [self.json jsonForKey:key];
}

#pragma mark 字典类方法

-(NSString*)description
{
//    return [self.originDict description];
    return [self stringForKey:@"description"];
}

- (NSString *)debugDescription
{
    return [super description];
}

@end
